home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xmcd-1.4 / libdi.d / vu_hita.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-10  |  12.2 KB  |  557 lines

  1. /*
  2.  *   libdi - CD Audio Player Device Interface Library
  3.  *
  4.  *   Copyright (C) 1995  Ti Kan
  5.  *   E-mail: ti@amb.org
  6.  *
  7.  *   This program is free software; you can redistribute it and/or modify
  8.  *   it under the terms of the GNU General Public License as published by
  9.  *   the Free Software Foundation; either version 2 of the License, or
  10.  *   (at your option) any later version.
  11.  *
  12.  *   This program is distributed in the hope that it will be useful,
  13.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *   GNU General Public License for more details.
  16.  *
  17.  *   You should have received a copy of the GNU General Public License
  18.  *   along with this program; if not, write to the Free Software
  19.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *   The name "Hitachi" is a trademark of Hitachi Corporation, and is
  22.  *   used here for identification purposes only.  This software and its
  23.  *   author are not affiliated in any way with Hitachi.
  24.  *
  25.  */
  26. #ifndef LINT
  27. static char *_vu_hita_c_ident_ = "@(#)vu_hita.c    5.4 94/12/28";
  28. #endif
  29.  
  30. #include "common.d/appenv.h"
  31. #include "common.d/util.h"
  32. #include "libdi.d/libdi.h"
  33. #include "libdi.d/scsipt.h"
  34.  
  35. #ifdef VENDOR_HITACHI
  36.  
  37. extern appdata_t    app_data;
  38. extern vu_tbl_t        scsipt_vutbl[];
  39.  
  40. STATIC bool_t        hita_paused = FALSE,        /* Currently paused */
  41.             hita_playing = FALSE,        /* Currently playing */
  42.             hita_audio_muted = FALSE;
  43.                             /* Audio is muted */
  44. STATIC word32_t        hita_pause_addr = 0;        /* Pause addr */
  45. STATIC haudio_arg_t    hita_sav_end;            /* Save addr */
  46.  
  47.  
  48. /*
  49.  * Internal functions
  50.  */
  51.  
  52. /*
  53.  * hita_do_pause
  54.  *    Send a vendor-unique Pause command to the drive
  55.  *
  56.  * Args:
  57.  *    ret_addr - Pointer to a buffer where the paused address will be
  58.  *           written to.  If NULL, no pause address info will
  59.  *           returned.
  60.  *
  61.  * Return:
  62.  *    TRUE - success
  63.  *    FALSE - failure
  64.  */
  65. STATIC bool_t
  66. hita_do_pause(hmsf_t *ret_addr)
  67. {
  68.     hmsf_t    pause_addr;
  69.     bool_t    ret;
  70.  
  71.     if ((ret = pthru_send(OP_VH_PAUSE, 0, (byte_t *) &pause_addr,
  72.                   SZ_VH_PAUSE, 0, 0, 0, 0, READ_OP,
  73.                   TRUE)) == TRUE) {
  74.         DBGDUMP("hita: Pause address", (byte_t *) &pause_addr,
  75.             sizeof(hmsf_t));
  76.  
  77.         if (ret_addr != NULL)
  78.             *ret_addr = pause_addr;    /* structure copy */
  79.     }
  80.     return (ret);
  81. }
  82.  
  83.  
  84. /*
  85.  * Public functions
  86.  */
  87.  
  88. /*
  89.  * hita_playaudio
  90.  *    Play audio function: send vendor-unique play audio command
  91.  *    to the drive.
  92.  *
  93.  * Args:
  94.  *    addr_fmt - Flags indicating which address formats are passed in
  95.  *    If ADDR_BLK, then:
  96.  *        start_addr - The logical block starting address
  97.  *        end_addr - The logical block ending address
  98.  *    If ADD_MSF, then:
  99.  *        start_msf - Pointer to the starting MSF address structure
  100.  *        end_msf - Pointer to the ending MSF address structure
  101.  *    If ADDR_TRKIDX, then:
  102.  *        trk - The starting track number
  103.  *        idx - The starting index number
  104.  *    If ADDR_OPTEND, then the ending address, if specified, can be
  105.  *    ignored if possible.
  106.  *
  107.  * Return:
  108.  *    TRUE - success
  109.  *    FALSE - failure
  110.  */
  111. /*ARGSUSED*/
  112. bool_t
  113. hita_playaudio(
  114.     byte_t        addr_fmt,
  115.     word32_t    start_addr,
  116.     word32_t    end_addr,
  117.     msf_t        *start_msf,
  118.     msf_t        *end_msf,
  119.     byte_t        trk,
  120.     byte_t        idx
  121. )
  122. {
  123.     msf_t        istart_msf,
  124.             iend_msf;
  125.     word32_t    addr1 = 0,
  126.             addr2 = 0;
  127.     haudio_arg_t    *a1,
  128.             *a2;
  129.     curstat_t    *s = curstat_addr();
  130.     bool_t        ret = FALSE;
  131.  
  132.     a1 = (haudio_arg_t *) &addr1;
  133.     a2 = (haudio_arg_t *) &addr2;
  134.  
  135.     if (!ret && (addr_fmt & ADDR_BLK) && !(addr_fmt & ADDR_MSF)) {
  136.         /* Convert block address to MSF format */
  137.         blktomsf(
  138.             start_addr,
  139.             &istart_msf.min, &istart_msf.sec, &istart_msf.frame,
  140.             MSF_OFFSET(s)
  141.         );
  142.  
  143.         blktomsf(
  144.             end_addr,
  145.             &iend_msf.min, &iend_msf.sec, &iend_msf.frame,
  146.             MSF_OFFSET(s)
  147.         );
  148.  
  149.         /* Let the ADDR_MSF code handle the request */
  150.         start_msf = &istart_msf;
  151.         end_msf = &iend_msf;
  152.         addr_fmt |= ADDR_MSF;
  153.         ret = FALSE;
  154.     }
  155.  
  156.     if (!ret && (addr_fmt & ADDR_MSF)) {
  157.         a1->addr_smin = (byte_t) start_msf->min;
  158.         a1->addr_ssec = (byte_t) start_msf->sec;
  159.         a1->addr_sframe = (byte_t) start_msf->frame;
  160.  
  161.         a2->addr_emin = hita_sav_end.addr_emin = (byte_t) end_msf->min;
  162.         a2->addr_esec = hita_sav_end.addr_esec = (byte_t) end_msf->sec;
  163.         a2->addr_eframe = hita_sav_end.addr_eframe = (byte_t)
  164.             end_msf->frame;
  165.  
  166.         /* Send a pause command to cease any current audio playback,
  167.          * then send the actual play audio command.
  168.          */
  169.         if ((ret = hita_do_pause(NULL)) == TRUE) {
  170.             ret = pthru_send(
  171.                 OP_VH_AUDPLAY, addr1, NULL, 0, 0, addr2,
  172.                 (byte_t) (hita_audio_muted ? 0x7 : 0x1),
  173.                 0, READ_OP, TRUE
  174.             );
  175.         }
  176.     }
  177.  
  178.     if (ret) {
  179.         hita_paused = FALSE;
  180.         hita_playing = TRUE;
  181.     }
  182.  
  183.     return (ret);
  184. }
  185.  
  186.  
  187. /*
  188.  * hita_pause_resume
  189.  *    Pause/resume function: send vendor-unique commands to implement
  190.  *    the pause and resume capability.
  191.  *
  192.  * Args:
  193.  *    resume - TRUE: resume, FALSE: pause
  194.  *
  195.  * Return:
  196.  *    TRUE - success
  197.  *    FALSE - failure
  198.  */
  199. bool_t
  200. hita_pause_resume(bool_t resume)
  201. {
  202.     word32_t    addr1 = 0,
  203.             addr2 = 0;
  204.     haudio_arg_t    *a1,
  205.             *a2;
  206.     hmsf_t        *a;
  207.     bool_t        ret = FALSE;
  208.  
  209.  
  210.     a1 = (haudio_arg_t *) &addr1;
  211.     a2 = (haudio_arg_t *) &addr2;
  212.     a = (hmsf_t *) &hita_pause_addr;
  213.  
  214.         if (resume) {
  215.         if (!hita_paused)
  216.             return TRUE;
  217.  
  218.         a1->addr_smin = a->min;
  219.         a1->addr_ssec = a->sec;
  220.         a1->addr_sframe = a->frame;
  221.         a2->addr_emin = hita_sav_end.addr_emin;
  222.         a2->addr_esec = hita_sav_end.addr_esec;
  223.         a2->addr_eframe = hita_sav_end.addr_eframe;
  224.  
  225.         ret = pthru_send(
  226.             OP_VH_AUDPLAY, addr1, NULL, 0, 0, addr2,
  227.             (byte_t) (hita_audio_muted ? 0x7 : 0x1),
  228.             0, READ_OP, TRUE
  229.         );
  230.         }
  231.         else {
  232.         if (hita_paused)
  233.             return TRUE;
  234.  
  235.         ret = hita_do_pause(a);
  236.     }
  237.  
  238.     if (ret) {
  239.         hita_paused = !resume;
  240.         hita_playing = !hita_paused;
  241.     }
  242.  
  243.     return (ret);
  244. }
  245.  
  246.  
  247. /*
  248.  * hita_start_stop
  249.  *    Start/stop function: When playing audio, the Hitachi drive must
  250.  *    first be paused before sending a Start/Stop Unit command to
  251.  *    stop it.
  252.  *
  253.  * Args:
  254.  *    start - TRUE: start unit, FALSE: stop unit
  255.  *    loej - TRUE: eject caddy, FALSE: do not eject
  256.  *
  257.  * Return:
  258.  *    TRUE - success
  259.  *    FALSE - failure
  260.  */
  261. bool_t
  262. hita_start_stop(bool_t start, bool_t loej)
  263. {
  264.     byte_t    param = 0x00;
  265.  
  266.     /* If audio playback is in progress, pause the playback.
  267.      * Then, return to caller (do_start_stop() in scsipt.c)
  268.      * and issue a start/stop unit command from there.
  269.      */
  270.     if (!start && hita_playing && !hita_do_pause(NULL))
  271.         return FALSE;
  272.  
  273.     hita_paused = FALSE;
  274.  
  275.     if (start)
  276.         param = 0x01;
  277.     else if (loej)
  278.         param = 0x02;
  279.  
  280.     return (
  281.         pthru_send(OP_S_START, 0, NULL, 0, 0, param, 0, 0, READ_OP, TRUE)
  282.     );
  283. }
  284.  
  285.  
  286. /*
  287.  * hita_get_playstatus
  288.  *    Send vendor-unique command to obtain current audio playback
  289.  *    status.
  290.  *
  291.  * Args:
  292.  *    s - Pointer to the curstat_t structure
  293.  *    audio_status - Address where a current status code (SCSI-2
  294.  *               style) is to be returned.
  295.  *
  296.  * Return:
  297.  *    TRUE - success
  298.  *    FALSE - failure
  299.  */
  300. bool_t
  301. hita_get_playstatus(curstat_t *s, byte_t *audio_status)
  302. {
  303.     int        trkno,
  304.             idxno;
  305.     byte_t        buf[SZ_VH_RDSTAT];
  306.     haudstat_t    *d;
  307.  
  308.  
  309.     memset(buf, 0, sizeof(buf));
  310.  
  311.     if (!pthru_send(OP_VH_RDSTAT, 0, buf, SZ_VH_RDSTAT, 0, 0, 0, 0,
  312.             READ_OP, TRUE))
  313.         return FALSE;
  314.  
  315.     DBGDUMP("hita: Read Status data bytes", buf, SZ_VH_RDSTAT);
  316.  
  317.     d = (haudstat_t *)(void *) buf;
  318.  
  319.     trkno = (word32_t) d->trkno;
  320.     if (s->cur_trk != trkno) {
  321.         s->cur_trk = trkno;
  322.         dpy_track(s);
  323.     }
  324.     idxno = 1;    /* Fudge */
  325.     if (s->cur_idx != idxno) {
  326.         s->cur_idx = idxno;
  327.         dpy_index(s);
  328.     }
  329.  
  330.     s->cur_tot_min = (byte_t) d->abs_addr.min;
  331.     s->cur_tot_sec = (byte_t) d->abs_addr.sec;
  332.     s->cur_tot_frame = (byte_t) d->abs_addr.frame;
  333.     s->cur_trk_min = (byte_t) d->rel_addr.min;
  334.     s->cur_trk_sec = (byte_t) d->rel_addr.sec;
  335.     s->cur_trk_frame = (byte_t) d->rel_addr.frame;
  336.     msftoblk(
  337.         s->cur_tot_min, s->cur_tot_sec, s->cur_tot_frame,
  338.         &s->cur_tot_addr, MSF_OFFSET(s)
  339.     );
  340.     msftoblk(
  341.         s->cur_trk_min, s->cur_trk_sec, s->cur_trk_frame,
  342.         &s->cur_trk_addr, 0
  343.     );
  344.  
  345.     /* Make up SCSI-2 style audio status */
  346.     if (hita_paused)
  347.         *audio_status = AUDIO_PAUSED;
  348.     else if (d->playing)
  349.         *audio_status = AUDIO_PLAYING;
  350.     else {
  351.         *audio_status = AUDIO_COMPLETED;
  352.         hita_playing = FALSE;
  353.     }
  354.  
  355.     return TRUE;
  356. }
  357.  
  358.  
  359. /*
  360.  * hita_get_toc
  361.  *    Send vendor-unique command to obtain the disc table-of-contents
  362.  *
  363.  * Args:
  364.  *    s - Pointer to the curstat_t structure, which contains the TOC
  365.  *        table to be updated.
  366.  *
  367.  * Return:
  368.  *    TRUE - success
  369.  *    FALSE - failure
  370.  */
  371. bool_t
  372. hita_get_toc(curstat_t *s)
  373. {
  374.     int        i,
  375.             j,
  376.             xfer_len;
  377.     byte_t        buf[SZ_VH_RDXINFO];
  378.     hxdiscinfo_t    *p;
  379.     hxmsf_t        *a;
  380.  
  381.  
  382.     if (hita_playing)
  383.         return FALSE;    /* Drive is busy */
  384.  
  385.     memset(buf, 0, sizeof(buf));
  386.  
  387.     /* Read the TOC header first */
  388.     if (!pthru_send(OP_VH_RDXINFO, 0, buf, SZ_VH_XTOCHDR,
  389.             SZ_VH_XTOCHDR & 0xff, SZ_VH_XTOCHDR >> 8, 0, 0,
  390.             READ_OP, TRUE))
  391.         return FALSE;
  392.  
  393.     p = (hxdiscinfo_t *)(void *) buf;
  394.  
  395.     s->first_trk = (byte_t) p->first_trk;
  396.     s->last_trk = (byte_t) p->last_trk;
  397.  
  398.     xfer_len = SZ_VH_XTOCHDR +
  399.            ((int) (p->last_trk - p->first_trk + 2) * SZ_VH_XTOCENT);
  400.  
  401.     if (xfer_len > SZ_VH_RDXINFO)
  402.         xfer_len = SZ_VH_RDXINFO;
  403.  
  404.     /* Read the appropriate number of bytes of the entire TOC */
  405.     if (!pthru_send(OP_VH_RDXINFO, 0, buf, xfer_len,
  406.             (byte_t) (xfer_len & 0xff), xfer_len >> 8, 0, 0,
  407.             READ_OP, TRUE))
  408.         return FALSE;
  409.  
  410.     DBGDUMP("hita: Read Extended Disc Info data bytes", buf, xfer_len);
  411.  
  412.     /* Get the starting position of each track */
  413.     for (i = 0, j = (int) s->first_trk; j <= (int) s->last_trk; i++, j++) {
  414.         a = (hxmsf_t *)(void *) &p->xmsfdata[(i+1) * SZ_VH_XTOCENT];
  415.         s->trkinfo[i].trkno = j;
  416.         s->trkinfo[i].min = (byte_t) a->min;
  417.         s->trkinfo[i].sec = (byte_t) a->sec;
  418.         s->trkinfo[i].frame = (byte_t) a->frame;
  419.         msftoblk(
  420.             s->trkinfo[i].min,
  421.             s->trkinfo[i].sec,
  422.             s->trkinfo[i].frame,
  423.             &s->trkinfo[i].addr,
  424.             MSF_OFFSET(s)
  425.         );
  426.         s->trkinfo[i].type = (a->trktype == 0) ? TYP_AUDIO : TYP_DATA;
  427.     }
  428.     s->tot_trks = (byte_t) i;
  429.  
  430.     /* Get the lead-out track position */
  431.     a = (hxmsf_t *)(void *) &p->xmsfdata[0];
  432.     s->trkinfo[i].trkno = LEAD_OUT_TRACK;
  433.     s->tot_min = s->trkinfo[i].min = (byte_t) a->min;
  434.     s->tot_sec = s->trkinfo[i].sec = (byte_t) a->sec;
  435.     s->tot_frame = s->trkinfo[i].frame = (byte_t) a->frame;
  436.     msftoblk(
  437.         s->trkinfo[i].min,
  438.         s->trkinfo[i].sec,
  439.         s->trkinfo[i].frame,
  440.         &s->trkinfo[i].addr,
  441.         MSF_OFFSET(s)
  442.     );
  443.     s->tot_addr = s->trkinfo[i].addr;
  444.  
  445.     return TRUE;
  446. }
  447.  
  448.  
  449. /*
  450.  * hita_mute
  451.  *    Send vendor-unique command to mute/unmute the audio
  452.  *
  453.  * Args:
  454.  *    mute - TRUE: mute audio, FALSE: un-mute audio
  455.  *
  456.  * Return:
  457.  *    TRUE - success
  458.  *    FALSE - failure
  459.  */
  460. bool_t
  461. hita_mute(bool_t mute)
  462. {
  463.     word32_t    addr1 = 0,
  464.             addr2 = 0;
  465.     haudio_arg_t    *a1,
  466.             *a2;
  467.     curstat_t    *s = curstat_addr();
  468.  
  469.  
  470.     if (mute == hita_audio_muted)
  471.         return TRUE;
  472.  
  473.     a1 = (haudio_arg_t *) &addr1;
  474.     a2 = (haudio_arg_t *) &addr2;
  475.  
  476.     if (hita_playing) {
  477.         /* Pause the playback first */
  478.             if (!hita_do_pause(NULL))
  479.             return FALSE;
  480.  
  481.         a1->addr_smin = (byte_t) s->cur_tot_min;
  482.         a1->addr_ssec = (byte_t) s->cur_tot_sec;
  483.         a1->addr_sframe = (byte_t) s->cur_tot_frame;
  484.         a2->addr_emin = hita_sav_end.addr_emin;
  485.         a2->addr_esec = hita_sav_end.addr_esec;
  486.         a2->addr_eframe = hita_sav_end.addr_eframe;
  487.  
  488.         if (!pthru_send(OP_VH_AUDPLAY, addr1, NULL, 0, 0, addr2,
  489.                 (byte_t) (mute ? 0x7 : 0x1), 0, READ_OP, TRUE))
  490.             return FALSE;
  491.     }
  492.  
  493.     hita_audio_muted = mute;
  494.  
  495.     return TRUE;
  496. }
  497.  
  498.  
  499. /*
  500.  * hita_eject
  501.  *    Send vendor-unique command to eject the caddy
  502.  *
  503.  * Args:
  504.  *    Nothing.
  505.  *
  506.  * Return:
  507.  *    TRUE - success
  508.  *    FALSE - failure
  509.  */
  510. bool_t
  511. hita_eject(void)
  512. {
  513.     /* If audio playback is in progress, pause the playback first */
  514.     if (hita_playing && !hita_do_pause(NULL))
  515.         return FALSE;
  516.  
  517.     hita_playing = hita_paused = FALSE;
  518.  
  519.     /* Eject the caddy */
  520.     return (
  521.         pthru_send(OP_VH_EJECT, 0, NULL, 0, 0x1, 0, 0, 0, READ_OP, TRUE)
  522.     );
  523. }
  524.  
  525.  
  526. /*
  527.  * hita_init
  528.  *    Initialize the vendor-unique support module
  529.  *
  530.  * Args:
  531.  *    Nothing.
  532.  *
  533.  * Return:
  534.  *    Nothing.
  535.  */
  536. void
  537. hita_init(void)
  538. {
  539.     /* Register vendor_unique module entry points */
  540.     scsipt_vutbl[VENDOR_HITACHI].vendor = "Hitachi";
  541.     scsipt_vutbl[VENDOR_HITACHI].playaudio = hita_playaudio;
  542.     scsipt_vutbl[VENDOR_HITACHI].pause_resume = hita_pause_resume;
  543.     scsipt_vutbl[VENDOR_HITACHI].start_stop = hita_start_stop;
  544.     scsipt_vutbl[VENDOR_HITACHI].get_playstatus = hita_get_playstatus;
  545.     scsipt_vutbl[VENDOR_HITACHI].volume = NULL;
  546.     scsipt_vutbl[VENDOR_HITACHI].route = NULL;
  547.     scsipt_vutbl[VENDOR_HITACHI].mute = hita_mute;
  548.     scsipt_vutbl[VENDOR_HITACHI].get_toc = hita_get_toc;
  549.     scsipt_vutbl[VENDOR_HITACHI].eject = hita_eject;
  550.     scsipt_vutbl[VENDOR_HITACHI].start = NULL;
  551.     scsipt_vutbl[VENDOR_HITACHI].halt = NULL;
  552. }
  553.  
  554.  
  555. #endif    /* VENDOR_HITACHI */
  556.  
  557.